package com.browsesoft.excel;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.Region;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.Text;

import com.browsesoft.Entity;
import com.browsesoft.ExtendElement;
import com.browsesoft.baseadapter.HTMLBasicTableModel;
import com.browsesoft.htmlcomponent.HTMLBasicComponent;
import com.browsesoft.htmlcomponent.HTMLPage;

/**
 */
public class ExcelServlet extends HttpServlet {

	/**
	 * table组件
	 */
	private HTMLBasicComponent component = null;

	/**
	 * 创建版本号
	 */
	private static final long serialVersionUID = 2854260569735092036L;

	public ExcelServlet() {
		super();
	}

	public void destroy() {
		super.destroy();
	}

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		try {
			// 得到导出模式,,前面的组件
			String exportModel = request.getParameter("exportmodel");
			String compId = request.getParameter("compid");
			this.component = HTMLPage.getComponentByID(request, compId);
			// 如果是全部导出模式
			HSSFWorkbook workBook = null;
			if (exportModel.equals("all")) {
				workBook = writeExcel();
			}
			// 如果是当页面导出模式
			else if (exportModel.equals("current")) {
				workBook = exportExcel();
			}
			// 输出到客户端
			out(workBook, response);
		} catch (Exception e) {
			throw new RuntimeException("读取文件失败!", e);
		}
	}

	/**
	 * The doPost method of the servlet.
	 */
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request, response);
	}

	public void init() throws ServletException {

	}

	/**
	 * 如果用户请求的资源未找到,应该返回的信息
	 * 
	 * @param response
	 *            响应
	 */
	protected void doFileNotFoundResponse(HttpServletResponse response) {
		// 设置响应状态为未找到请求的资源
		response.setStatus(HttpServletResponse.SC_NOT_FOUND);
		response.setContentType("text/html; charset=gb2312");
		// 给用户信息提示
		try {
			response.getWriter().write("<h1>您要的资源未找到.!</h1>");
		} catch (IOException ex) {
		}
	}

	/**
	 * 输出
	 */
	private void out(HSSFWorkbook workBook, HttpServletResponse response)
			throws Exception {
		// 产生临时文件
		File file = File.createTempFile("temp", ".xls");
		FileOutputStream fileOutputStream = new FileOutputStream(file);
		// 写文件
		workBook.write(fileOutputStream);
		// 清缓存
		response.setStatus(HttpServletResponse.SC_OK);
		response.setContentType("application/octet-stream;charset=\"gb2312\"");
		response.addHeader("Content-Disposition", "attachment;filename=\" "
				+ file.getName() + "\"");
		// 把文件的内容送入响应流中
		byte[] b = new byte[1024];
		BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
				file));
		BufferedOutputStream bos = new BufferedOutputStream(response
				.getOutputStream());
		while (bis.read(b) != -1) {
			bos.write(b);
		}
		bis.close();
		file.deleteOnExit();
		bos.close();
	}

	/**
	 * 当前页面导出模式导出excel
	 */
	private HSSFWorkbook exportExcel() throws Exception {
		// 得到含有excel="excel"的区域标记，带有该标记下的table元素为需要导出的内容
		Element elem = (Element) ExtendElement.findElements(
				this.component.getElement(), "excel", "excel").get(0);
		// 如果是再excel元素中配置有 sheet="sheets", 是多个sheet方式, 每一个的table的数据 导出到一个sheet上
		if (elem.getAttribute("sheet") != null
				&& elem.getAttribute("sheet").equals("sheets")) {
			return writeExcelByDocforSheets(elem);
		}
		// 否则，是单个sheet方式, 所有的数据导出到一个sheet上
		else {
			return writeExcelByDoc(elem);
		}
	}

	/**
	 * 把tableModel中的当前所有数据导出到Excel
	 */
	public HSSFWorkbook writeExcel() throws Exception {
		HTMLBasicTableModel model = (HTMLBasicTableModel) this.component
				.getModel();
		// 创建一个工作薄
		HSSFWorkbook workbook = new HSSFWorkbook();
		// 创建新的一页
		HSSFSheet sheet = workbook.createSheet();
		// 设置字体
		HSSFFont font = workbook.createFont();
		font.setColor((short) HSSFFont.COLOR_NORMAL);
		font.setBoldweight((short) HSSFFont.BOLDWEIGHT_BOLD);
		// 设置格式
		HSSFCellStyle cellStyle = workbook.createCellStyle();
		cellStyle.setAlignment((short) HSSFCellStyle.ALIGN_CENTER);
		cellStyle.setFont(font);
		// 定义行和列
		HSSFRow row = null;
		HSSFCell cell = null;
		// 创建第0行 标题
		row = sheet.createRow((short) 0);
		for (int titleCol = 0; titleCol < model.getColumnCount(); titleCol++) {
			cell = row.createCell((short) titleCol);
			// 设置列类型
			cell.setCellType(HSSFCell.CELL_TYPE_STRING);
			// 设置列的字符集为中文
			cell.setEncoding((short) HSSFCell.ENCODING_UTF_16);
			// 设置内容
			cell.setCellValue(model.getColumnName(titleCol));
			cell.setCellStyle(cellStyle);
		}
		// 填写数据
		List datas = (List) model.getDatas();
		int rowNumber = 1;
		// 循环创建每一行
		Iterator iter = datas.iterator();
		while (iter.hasNext()) {
			// 得到一个实体数据
			Entity entity = (Entity) iter.next();
			row = sheet.createRow((short) rowNumber);
			// 创建每一列
			for (int col = 0; col < model.getColumnCount(); col++) {
				// 得到数据
				String ename = model.getColumnEname(col);
				String data = (String) entity.getAttributes().get(ename);
				if (data == null) {
					data = "";
				}
				cell = row.createCell((short) col);
				// 设置列类型
				cell.setCellType(HSSFCell.CELL_TYPE_STRING);
				// 设置列的字符集为中文
				cell.setEncoding((short) HSSFCell.ENCODING_UTF_16);
				cell.setCellValue(data);
			}
			rowNumber++;
		}

		return workbook;
	}

	/**
	 * 获得最大的行数
	 * 
	 */
	public int getRowNumber(Element e) throws Exception {
		int result = 0;
		int row = 0;
		for (int i = 0; i < e.getChildNodes().getLength(); i++) {
			Node ee = e.getChildNodes().item(i);
			if (ee.getNodeName().equals("tr")) {
				row++;
			}
		}
		result = row;
		return result;
	}

	/**
	 * 获得某一节点下最大的列数
	 * 
	 */
	public int getColNumber(Element e) throws Exception {
		int result = 0;
		int tcol = 0;
		int col = 0;
		for (int i = 0; i < e.getChildNodes().getLength(); i++) {
			Node ee = e.getChildNodes().item(i);
			if (ee.getNodeName().equals("tr")) {
				for (int j = 0; j < ee.getChildNodes().getLength(); j++) {
					Node td = ee.getChildNodes().item(j);
					// 获得表单的每一行的每一单元格
					if (td.getNodeName().equals("td")) {
						tcol++;
					}
				}
				if (tcol > col) {
					col = tcol;
				}
				tcol = 0;
			}
		}
		result = col;
		return result;
	}

	/**
	 * 获得某一行中不在合并区域的有效列数
	 * 
	 */
	public int getValidcol(LinkedList lk, int rowNumber, int colNumber) {
		int n = 0;
		Region reg = null;
		// 循环判断（rowNumber,colNumber）是否在合并的区域内部
		for (int i = 0; i < lk.size(); i++) {
			reg = (Region) lk.get(i);
			if (reg.contains(rowNumber, (short) colNumber)) {
				colNumber++;
			} else {
				n++;
			}
		}
		if (n < lk.size()) {
			colNumber = getValidcol(lk, rowNumber, colNumber);
		}
		return colNumber;
	}

	/**
	 * 获得Select选择框的内容
	 * 
	 */
	public String getSelectContent(Node n) {
		String result = null;
		Element nn = (Element) ExtendElement.findElements((Element) n,
				"selected", "selected").getFirst();
		Node m = nn.getFirstChild();
		if (m.getNodeType() == Node.TEXT_NODE) {
			result = ((Text) m).getNodeValue();
		} else {
			result = "";
		}
		return result;
	}

	/**
	 * 获得textarea 文本区域的内容
	 * 
	 */
	public String getTextareaContent(Node n) {
		String result = null;
		Node m = n.getFirstChild();
		if (m.getNodeType() == Node.TEXT_NODE) {
			result = ((Text) m).getNodeValue();
		} else {
			result = "";
		}
		return result;
	}

	/**
	 * 获得div的内容
	 * 
	 */
	public String getDivContent(Node n) {
		String result = null;
		Node m = n.getFirstChild();
		if (m.getNodeType() == Node.TEXT_NODE) {
			result = ((Text) m).getNodeValue();
		} else {
			result = "";
		}
		return result;
	}

	/**
	 * 把页面数据导出到Excel 所有数据导出到一个sheet中
	 * 
	 * @throws Exception
	 */
	public HSSFWorkbook writeExcelByDoc(Element elem) throws Exception {
		// 创建一个工作薄
		HSSFWorkbook workbook = new HSSFWorkbook();
		// 创建新的一页
		HSSFSheet sheet = workbook.createSheet();
		// 定义行和列
		HSSFRow row = null;
		HSSFCell cell = null;
		// 定义行号r 用来保存当前是第几行
		int rowNumber = -1;
		// 定义列号c 用来保存当前是第几列
		int colNumber = -1;
		// 定义合并的行数
		int rowspan = 0;
		// 定义合并的行数
		int colspan = 0;
		// 定义合并域的likedlist
		LinkedList mergerAreas = new LinkedList();
		// 定义一个合并区域
		Region reg = null;
		// 定义表节点（元素）
		Element e_table = null;
		Element node_excel = (Element) ExtendElement.findElements(elem,
				"excel", "excel").getFirst();
		// e_table =(Element) node_excel.getElementsByTagName("table").item(0);
		// //获得最大的行数和最大的列数
		// int maxRowNum = getRowNumber(e_table);
		// int maxColNum = getColNumber(e_table);
		// //定义合并区域
		// reg = new Region(0, (short) 0, 0, (short) (maxColNum - 1));
		// sheet.addMergedRegion(reg);
		// //创建第1行
		// row = sheet.createRow( (short) 1);
		// 查看文挡(doc)里面有几个table 每一个table进行循环
		for (int n = 0; n < node_excel.getElementsByTagName("table")
				.getLength(); n++) {
			// 获得每一个table元素
			e_table = (Element) node_excel.getElementsByTagName("table")
					.item(n);
			for (int i = 0; i < e_table.getElementsByTagName("tr").getLength(); i++) {
				Element node_tr = (Element) e_table.getElementsByTagName("tr")
						.item(i);
				// 获得表单的每一行
				if (node_tr.getNodeName().equals("tr")) {
					rowNumber++;
					// 创建第rowNumber行
					row = sheet.createRow((short) (rowNumber));
					colNumber = -1;
					for (int j = 0; j < node_tr.getElementsByTagName("td")
							.getLength(); j++) {
						Node node_td = node_tr.getElementsByTagName("td").item(
								j);
						// 获得表单的每一行的每一单元格
						if (node_td.getNodeName().equals("td")) {
							colNumber++;
							// 获得合并的行数
							String tmp = null;
							tmp = ((Element) node_td).getAttribute("rowspan");
							if (tmp != null && !tmp.equals("")) {
								rowspan = Integer.parseInt(tmp) - 1;
							} else {
								rowspan = 0;
							}
							// 获得合并的列数
							tmp = ((Element) node_td).getAttribute("colspan");
							if (tmp != null && !tmp.equals("")) {
								colspan = Integer.parseInt(tmp) - 1;
							} else {
								colspan = 0;
							}
							// 创建合并区域
							if (rowspan > 0 || colspan > 0) {
								// 创建列
								cell = row.createCell((short) colNumber);
								// 设置列类型
								cell.setCellType(HSSFCell.CELL_TYPE_STRING);
								// 设置列的字符集为中文
								cell
										.setEncoding((short) HSSFCell.ENCODING_UTF_16);
								// 设置内容
								// cell.setCellValue("hello");
								// 创建合并区域
								reg = new Region(rowNumber, (short) colNumber,
										(rowNumber + rowspan),
										(short) (colNumber + colspan));
								// 在mergerAeeans中添加合并区域
								mergerAreas.add(reg);
								// 在Sheet中创建合并区域
								sheet.addMergedRegion(reg);
							} else {
								// 寻找不在合并区域的列号
								colNumber = getValidcol(mergerAreas, rowNumber,
										colNumber);
								// 创建列
								cell = row.createCell((short) colNumber);
								// 设置列类型
								cell.setCellType(HSSFCell.CELL_TYPE_STRING);
								// 设置列的字符集为中文
								cell
										.setEncoding((short) HSSFCell.ENCODING_UTF_16);
								// 设置内容
								// cell.setCellValue("hello");
							}
							Node td1 = node_td.getChildNodes().item(0);
							LinkedList lk = ExtendElement
									.findElementContext(node_td);
							if (lk.size() > 0
									&& !((Text) lk.get(0)).getNodeValue()
											.trim().equals("")) {
								String content = ((Text) lk.get(0))
										.getNodeValue().trim();
								// 设置内容
								cell.setCellValue(content);
							} else {
								// 如果是元素
								if (td1 instanceof Element) {
									Element c2 = (Element) node_td
											.getFirstChild();
									// 如果是Input 文本输入框
									if (c2.getNodeName().equals("input")) {
										// 设置内容
										cell.setCellValue(c2
												.getAttribute("value"));
									}
									// 如果是Select 文本选择框
									else if (c2.getNodeName().equals("select")) {
										// 设置内容
										cell.setCellValue(getSelectContent(c2));
									}
									// 如果是div
									else if (c2.getNodeName().equals("div")) {
										// 设置内容
										cell.setCellValue(getDivContent(c2));
									}
								}
								// 如果是其他
								else {
									// 设置内容
									cell.setCellValue("");
								}
							}
						}
					}
				}
			} // end for table
		} // end for doc
		return workbook;
	}

	/**
	 * 把页面数据导出到Excel 每个table的数据导出到一个sheet中
	 * 
	 * @throws Exception
	 */
	public HSSFWorkbook writeExcelByDocforSheets(Element elem) throws Exception {
		// 创建一个工作薄
		HSSFWorkbook workbook = new HSSFWorkbook();
		// 定义一页
		HSSFSheet sheet = null;
		// 定义行和列
		HSSFRow row = null;
		HSSFCell cell = null;
		// 定义行号r 用来保存当前是第几行
		int rowNumber = -1;
		// 定义列号c 用来保存当前是第几列
		int colNumber = -1;
		// 定义合并的行数
		int rowspan = 0;
		// 定义合并的行数
		int colspan = 0;
		// 定义合并域的likedlist
		LinkedList mergerAreas = new LinkedList();
		// 定义一个合并区域
		Region reg = null;
		// 定义表节点（元素）
		Element e_table = null;
		// 获得导出的位置
		Element node_excel = (Element) ExtendElement.findElements(elem,
				"excel", "excel").getFirst();
		// 查看文挡(doc)里面有几个table 每一个table进行循环
		for (int n = 0; n < node_excel.getElementsByTagName("table")
				.getLength(); n++) {
			// 获得每一个table元素
			e_table = (Element) node_excel.getElementsByTagName("table")
					.item(n);
			// 创建一个新页面
			sheet = workbook.createSheet();
			// 清空合并区域的内容
			mergerAreas.clear();
			// 重新设置行号
			rowNumber = -1;
			for (int i = 0; i < e_table.getChildNodes().getLength(); i++) {
				Node node_tr = e_table.getChildNodes().item(i);
				// 获得表单的每一行
				if (node_tr.getNodeName().equals("tr")) {
					rowNumber++;
					// 创建第rowNumber行
					row = sheet.createRow((short) (rowNumber));
					colNumber = -1;
					for (int j = 0; j < node_tr.getChildNodes().getLength(); j++) {
						Node node_td = node_tr.getChildNodes().item(j);
						// 获得表单的每一行的每一单元格
						if (node_td.getNodeName().equals("td")) {
							colNumber++;
							// 获得合并的行数
							String tmp = null;
							tmp = ((Element) node_td).getAttribute("rowspan");
							if (tmp != null && !tmp.equals("")) {
								rowspan = Integer.parseInt(tmp) - 1;
							} else {
								rowspan = 0;
							}
							// 获得合并的列数
							tmp = ((Element) node_td).getAttribute("colspan");
							if (tmp != null && !tmp.equals("")) {
								colspan = Integer.parseInt(tmp) - 1;
							} else {
								colspan = 0;
							}
							// 创建合并区域
							if (rowspan > 0 || colspan > 0) {
								// 创建列
								cell = row.createCell((short) colNumber);
								// 设置列类型
								cell.setCellType(HSSFCell.CELL_TYPE_STRING);
								// 设置列的字符集为中文
								cell
										.setEncoding((short) HSSFCell.ENCODING_UTF_16);
								// 设置内容
								// cell.setCellValue("hello");
								// 创建合并区域
								reg = new Region(rowNumber, (short) colNumber,
										(rowNumber + rowspan),
										(short) (colNumber + colspan));
								// 在mergerAeeans中添加合并区域
								mergerAreas.add(reg);
								// 在Sheet中创建合并区域
								sheet.addMergedRegion(reg);
							} else {
								// 寻找不在合并区域的列号
								colNumber = getValidcol(mergerAreas, rowNumber,
										colNumber);
								// 创建列
								cell = row.createCell((short) colNumber);
								// 设置列类型
								cell.setCellType(HSSFCell.CELL_TYPE_STRING);
								// 设置列的字符集为中文
								cell
										.setEncoding((short) HSSFCell.ENCODING_UTF_16);
								// 设置内容
								// cell.setCellValue("hello");
							}
							Node td1 = node_td.getChildNodes().item(0);
							// 如果是元素
							if (td1 instanceof Element) {
								Element c2 = (Element) node_td.getFirstChild();
								// 如果是Input 文本输入框
								if (c2.getNodeName().equals("input")) {
									// 设置内容
									cell.setCellValue(c2.getAttribute("value"));
								}
								// 如果是Select 文本选择框
								else if (c2.getNodeName().equals("select")) {
									// 设置内容
									cell.setCellValue(getSelectContent(c2));
								}
								// 如果是textarea文本选择框
								else if (c2.getNodeName().equals("textarea")) {
									// 设置内容
									cell.setCellValue(getTextareaContent(c2));
								}
								// 如果是div
								else if (c2.getNodeName().equals("div")) {
									// 设置内容
									cell.setCellValue(getDivContent(c2));
								}
							}
							// 如果是文本
							else if (td1 instanceof Text) {
								// 设置内容
								cell.setCellValue(((Text) td1).getNodeValue());
							}
							// 如果是其他
							else {
								// 设置内容
								cell.setCellValue("");
							}
						}
					}
				}
			}
		}
		return workbook;
	}
}
